package com.tange.ai.iot.client.gnssa.glide

import android.util.Base64
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey
import java.io.ByteArrayInputStream
import java.io.InputStream

class Base64ModelLoader : ModelLoader<String, InputStream> {

    override fun buildLoadData(
        model: String,
        width: Int,
        height: Int,
        options: Options
    ): ModelLoader.LoadData<InputStream> {
        return ModelLoader.LoadData(
            ObjectKey(model),
            Base64DataFetcher(model)
        )
    }

    override fun handles(model: String): Boolean {
        return model.startsWith("data:image") ||
                model.startsWith("base64:") ||
                model.matches(Regex("^[A-Za-z0-9+/=]+$"))
    }

    private class Base64DataFetcher(private val base64String: String) :
        DataFetcher<InputStream> {

        override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
            try {
                val pureBase64 = base64String.substringAfterLast(",")
                val decodedBytes = Base64.decode(pureBase64, Base64.DEFAULT)
                callback.onDataReady(ByteArrayInputStream(decodedBytes))
            } catch (e: Exception) {
                callback.onLoadFailed(e)
            }
        }

        override fun cleanup() {}
        override fun cancel() {}
        override fun getDataClass(): Class<InputStream> = InputStream::class.java
        override fun getDataSource(): DataSource = DataSource.LOCAL
    }
}

class Base64ModelLoaderFactory : ModelLoaderFactory<String, InputStream> {
    override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<String, InputStream> {
        return Base64ModelLoader()
    }

    override fun teardown() {}
}